package com.scr1pt.fileshare2.controller

import com.github.hui.quick.plugin.qrcode.wrapper.QrCodeGenWrapper
import com.github.hui.quick.plugin.qrcode.wrapper.QrCodeOptions
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel
import com.scr1pt.extension.*
import com.scr1pt.fileshare2.model.ShareConfig
import com.scr1pt.fileshare2.model.FileTable
import com.scr1pt.fileshare2.model.FileTableItem
import com.scr1pt.fileshare2.utils.Static.Companion.deleteZipFile
import com.scr1pt.fileshare2.utils.Zip
import com.scr1pt.fileshare2.utils.getIP
import com.scr1pt.fileshare2.utils.handlePath
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RequestParam
import org.springframework.web.bind.annotation.RestController
import java.awt.Color
import java.io.File
import java.util.*
import javax.servlet.http.HttpServletRequest
import javax.servlet.http.HttpServletResponse
import javax.servlet.http.HttpSession

/**
 * 说明: TODO
 *
 * 创建者: tum0r
 *
 * 时间: 2022/2/3 21:52
 */
@RestController
@RequestMapping("/files")
class FileController {
    @Autowired
    private lateinit var shareConfig: ShareConfig

    /**
     * 获取文件列表
     */
    @RequestMapping("/list")
    fun list(@RequestParam("path") path: String?, request: HttpServletRequest): FileTable {
        val accessPath = path.handlePath()
        val folder = File("${shareConfig.share}$accessPath".replace("/", File.separator))
        val result = FileTable()
        if (shareConfig.share.checkDirThrough(folder.path)) {
            if (!folder.isExistsFolder()) folder.mkdirs()
            val files = folder.listFiles()
            if (files.isNotNullOrEmpty()) {
                var baseURL = request.requestURL.toString()
                baseURL = baseURL.substring(0, baseURL.indexOf("/files/list"))
                val data = result.data
                for (file in files!!) {
                    if (!(file.isExistsFile() || file.isExistsFolder())) continue
                    val fileName = file.name
                    val downloadLink = "$baseURL/files/download?path=$accessPath$fileName"
                    val item = FileTableItem(accessPath, downloadLink, fileName, file.isExistsFolder(), "$baseURL/files/getQRCode?address=${downloadLink.urlEncode()}", file.getFileSize(), Date(file.lastModified()))
                    item.calc()
                    data.add(item)
                }
                data.sort()
                for (i in data.indices) data[i].ID = i + 1
                result.count = data.size
            }
        } else {
            result.code = 403
            result.msg = "文件目录不可访问"
        }
        return result
    }

    @RequestMapping("/download")
    fun download(@RequestParam("path") path: String?, response: HttpServletResponse, request: HttpServletRequest): String? {
        val accessPath = path.handlePath()
        var file = File("${shareConfig.share}$accessPath".replace("/", File.separator))
        if (!shareConfig.share.checkDirThrough(file.path)) return "文件目录不可访问"
        else if (!(file.isExistsFile() || file.isExistsFolder())) return "文件不存在"
        var fileName = file.name
        if (file.isExistsFolder()) {
            val tmpPath = shareConfig.tmp + File.separator
            tmpPath.createDir()
            val zipFile = File("$tmpPath${fileName}_${request.getIP().replace(".", "_")}.zip")
            val zip = Zip(zipFile)
            zip.addFiles(file)
            zip.compress()
            file = zipFile
            fileName += ".zip"
            deleteZipFile[fileName] = file
        }
        response.reset()
        response.contentType = MIMEExtension.getMIME(file.extension)[1]
        response.setContentLengthLong(file.length())
        response.setHeader("Content-Disposition", "attachment;filename=${if (shareConfig.urlEncode) fileName.urlEncode() else fileName}")
        val outputStream = response.outputStream
        file.forEachBlock(shareConfig.blockSize) { data, count ->
            outputStream.write(data, 0, count)
            outputStream.flush()
        }
        closeableClose(outputStream)
        deleteZipFile[fileName]?.delete()
        return null
    }

    @RequestMapping("/getQRCode")
    fun getQRCode(@RequestParam("address") address: String, session: HttpSession): String {
        var result = session.getAttribute(address) as String?
        if (result.isNullOrBlank()) {
            val builder = QrCodeGenWrapper.of(address).setH(300).setW(300).setPadding(1).setPicType("png")
                .setErrorCorrection(ErrorCorrectionLevel.Q).setDrawStyle(QrCodeOptions.DrawStyle.RECT)
                .setDetectSpecial().setDetectOutColor(Color.CYAN).setDetectInColor(Color.ORANGE).setDrawPreColor(Color.RED)
            result = "data:image/png;base64,${builder.asString()}"
            session.setAttribute(address, result)
        }
        return result!!
    }
}